home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / Music / EDIT / PerfectSound / source / sed4.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-23  |  25.0 KB  |  1,183 lines

  1. /********************************/
  2. /**   Perfect Sound (C) 1986   **/
  3. /**    Anthony J. Wood         **/
  4. /**                            **/
  5. /** FILE 4 of 4                **/
  6. /**                            **/
  7. /** This Source code may be    **/
  8. /** copied for backup only.    **/
  9. /** This Source code is for    **/
  10. /** reference only, you may    **/
  11. /** NOT modify and compile     **/
  12. /** this source except for     **/
  13. /** PERSONAL use. Permission   **/
  14. /** is given to distribute     **/
  15. /** copies of the object code  **/
  16. /** generated from compiling   **/
  17. /** Perfect Sound ONLY if the  **/
  18. /** source code is not changed **/
  19. /** in any way. Permision is   **/
  20. /** granted to use subroutines **/
  21. /** in this file within your   **/
  22. /** own programs if you notify **/
  23. /** SunRize Industries of your **/
  24. /** intent to do so and        **/
  25. /** SunRize Industries agrees  **/
  26. /** to your request.           **/
  27. /**                            **/
  28. /**  SunRize Industries        **/
  29. /**  PO Box 1453               **/
  30. /**  College Station, TX 77841 **/
  31. /**  (409) 846-1311            **/
  32. /**                            **/
  33. /********************************/
  34.  
  35. #include <exec/types.h>
  36. #include <stdio.h>
  37. #include <exec/exec.h>
  38. #include <fcntl.h>
  39. #include <intuition/intuition.h>
  40. #include "libraries/dos.h"
  41. #include "df0:sed1.h"
  42.  
  43.  
  44. #define SHOW 8      /* no. of samples to display in load requester */
  45. #define IHI 50      /* height of getint requester */
  46. #define SHI 30
  47.  
  48. WORD delta[16]={-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21};
  49.  
  50. /********************************/
  51. /*  save current sample to disk */
  52. /********************************/
  53.  
  54. save_samp (Window,current,samp,fname)
  55.  
  56. struct Samp *samp;
  57. struct Window *Window;
  58. int current;
  59. char *fname;
  60. {
  61. int fp;
  62. char line[80];
  63. if (samp->lmem[current]==0) return(-1);
  64. sprintf(line,"Writing: %s",fname);
  65. msg(Window,line);
  66. if ((fp=open(fname,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  67.    msg(Window,"ERROR opening file for write");
  68.    return(-1);
  69.    }
  70.  
  71. if (samp->type[current]==LEFT || samp->type[current]==STEREO)
  72.    if (write(fp,samp->lmem[current],samp->length[current])==-1) {
  73.       msg(Window,"ERROR writing to disk file!");
  74.       close(fp);
  75.       return(-1);
  76.       }
  77. if (samp->type[current]==RIGHT || samp->type[current]==STEREO)
  78.    if (write(fp,samp->rmem[current],samp->length[current])==-1) {
  79.       msg(Window,"ERROR writing to disk file!");
  80.       close(fp);
  81.       return(-1);
  82.       }
  83.  
  84.    msg(Window,"Finished Writing Dump... No Errors");
  85. close(fp);
  86. return(0);
  87. }
  88.  
  89.  
  90. save_IFF (Window,current,samp,fname,comp)
  91.  
  92. struct Samp *samp;
  93. struct Window *Window;
  94. int current,comp;
  95. char *fname;
  96. {
  97. int fp;
  98. ULONG i,len,evenlen;
  99. UWORD j;
  100. UBYTE k;
  101. char line[80];
  102. if (samp->lmem[current]==0) return(-1);
  103. sprintf(line,"Writing: %s",fname);
  104. msg(Window,line);
  105. if ((fp=open(fname,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  106.    msg(Window,"ERROR opening file for write");
  107.    return(-1);
  108.    }
  109.  
  110. evenlen=samp->length[current]&(~1);   /*make length an even number */
  111. if (evenlen!=samp->length[current])
  112.    msg(Window,"Warning last byte lost--length must be even.");
  113.  
  114. len=evenlen;
  115.  
  116. if (samp->type[current]==STEREO) len=len*2;
  117. j=(UWORD)(1.0/((float)samp->rate[current]*.279365*1e-6));
  118.  
  119. write(fp,"FORM",4);
  120. if (comp==FALSE) i=4+28+76+8+len+12;
  121. else {
  122.    i=4+28+76+8+(len>>1)+2+12;
  123.    if (samp->type[current]==STEREO) i=i+2;
  124.    }
  125. write(fp,&i,4);
  126. write(fp,"8SVXVHDR",8);
  127. i=20; write(fp,&i,4);
  128.  
  129. if (samp->oneshot[current]==0 || samp->oneshot[current]==1)
  130.    write(fp,&len,4);    /* # of samples field */
  131. else 
  132.    write(fp,&samp->oneshot[current],4);
  133. write(fp,&samp->repeat[current],4);
  134. write(fp,&samp->cycles[current],4);
  135. write(fp,&j,2);
  136.  
  137. k=1;
  138. if (samp->oneshot[current]==0)
  139.   write(fp,&k,1);
  140. else
  141.    write(fp,&samp->ctoctave[current],1);
  142.  
  143. k=0;if (comp==TRUE) k=1;
  144. write(fp,&k,1);   /* compression */
  145. i=0x10000;   /*max volume */
  146. write(fp,&i,4);
  147.  
  148. write(fp,"ANNO",4);
  149. i=68; write(fp,&i,4);
  150. write(fp,"Recorded with PERFECT SOUND from SunRize Industries.  (409) 846-1311",
  151.           68);
  152.  
  153. /* The following new chuck CHAN is 4 bytes long and is used to store
  154.   channel information (RIGHT, LEFT, STEREO --see sed1.h) */
  155.  
  156. write(fp,"CHAN",4);  /* non standard channel chunck */
  157. i=4;write(fp,&i,4);  /* length */
  158. write(fp,&samp->type[current],4);
  159.  
  160. write(fp,"BODY",4);
  161. len=evenlen;
  162. if (comp==TRUE) len=(len>>1)+2;
  163. if (samp->type[current]==STEREO) len=len*2;
  164. write(fp,&len,4);
  165.  
  166. if (samp->type[current]==LEFT || samp->type[current]==STEREO) {
  167.    if (comp==FALSE) i=write(fp,samp->lmem[current],evenlen);
  168.    if (comp==TRUE)  i=cwrite(fp,samp->lmem[current],evenlen);
  169.    if (i==-1) {
  170.       msg(Window,"ERROR writing to file!");
  171.       close(fp);
  172.       return(-1);
  173.       }
  174.    }
  175.  
  176. if (samp->type[current]==RIGHT || samp->type[current]==STEREO) {
  177.    if (comp==FALSE) i=write(fp,samp->rmem[current],evenlen);
  178.    if (comp==TRUE)  i=cwrite(fp,samp->rmem[current],evenlen);
  179.    if (i==-1) {
  180.       msg(Window,"ERROR writing to file!");
  181.       close(fp);
  182.       return(-1);
  183.       }
  184.    }
  185.  
  186. if (comp==FALSE) msg(Window,"Finished Writing... No Errors");
  187. else {
  188.      sprintf(line,"File Writen with %d%% of samples altered during compression.",i);
  189.      msg(Window,line);
  190.      }
  191. close(fp);
  192. return(0);
  193. }                              
  194.  
  195. /*******************************/
  196. /** compressed write          **/
  197. /*******************************/
  198.  
  199. cwrite(fp,data,len)
  200. int fp,len;
  201. BYTE *data;
  202. {
  203. WORD prev=0;
  204. register int pererr=0;
  205. register int i;
  206. register int k,j;
  207. int bpos;
  208. char val;
  209. BYTE buf[512];
  210.  
  211. if (write(fp,&prev,1)==-1) return(-1);   /* padding */
  212. prev=*data;
  213. if (write(fp,data,1)==-1) return(-1);    /* 1st value */
  214. i=len/2;
  215. bpos=0;
  216.  
  217. for (k=0;k<i;k++) {
  218.    for (j=1;j<16;j++)
  219.       if ((prev+delta[j]) > (WORD)*data) break;
  220.    j--;
  221.    if (prev+delta[j] < -128) j++;
  222.    val=j;
  223.    prev=prev+delta[j];
  224.    if (prev!=*data) pererr++;
  225.    data++;
  226.    for (j=1;j<16;j++)
  227.       if ((prev+delta[j]) > (WORD)*data) break;
  228.    j--;
  229.    if (prev+delta[j] < -128) j++;
  230.    val=(val<<4)|j;
  231.    prev=prev+delta[j];
  232.    if (prev!=*data) pererr++;
  233.    data++;
  234.  
  235.    buf[bpos++]=val;
  236.    if (bpos==512) {
  237.       bpos=0;
  238.       if (write(fp,buf,512)==-1) return(-1);
  239.       }
  240.    }
  241.    if (bpos!=0)
  242.       if (write(fp,buf,bpos)==-1) return(-1);
  243. return(pererr*100/len);
  244. }
  245.  
  246. /********************************/
  247. /*  Load a new sample from disk */
  248. /********************************/
  249.  
  250. load_samp (Window,current,samp,path)
  251.  
  252. int *current;
  253. struct Samp  *samp;
  254. struct Window *Window;
  255. char *path;
  256.  
  257. {
  258. char name[80],fname[80],line[80];
  259. name[0]=0;
  260.  
  261. if (getfile(Window,name,path,"LOAD","Load a Sample")==-1) return(-1);
  262.  
  263. strcpy(fname,path);
  264. add(fname,name);       /* fname is now path+filename */
  265.  
  266. sprintf(line,"Loading: %s",fname);
  267. msg(Window,line);
  268. return(load_it(Window,current,samp,fname,name));
  269. }
  270.  
  271.  
  272. /*****************************************/
  273. /** perform load once got file and path **/
  274. /*****************************************/
  275.  
  276. load_it(Window,current,samp,fname,name)
  277.  
  278. int *current;
  279. struct Samp  *samp;
  280. struct Window *Window;
  281. char *fname,*name;
  282.  
  283. {
  284. int in,i,len;
  285. ULONG k,x;
  286. UWORD e1,e2,z;
  287. long pos;
  288. static char line[80];
  289. UBYTE comp=0;
  290.  
  291. if ((i=getslot(Window,samp))==-1) return(-1);
  292. if ((in=(int)open(fname,O_RDONLY))==-1) {
  293.    msg(Window,"Can't open that file.");
  294.    return(-1);
  295.    }
  296.  
  297. read(in,&k,4);
  298. if (k!=FORM) {         /* not in standard form */
  299.    samp->rate[i]=350;           /* default length */
  300.    samp->type[i]=LEFT;          /* use left (ch 0) as default */
  301.    pos=lseek(in,0L,2);
  302.    samp->length[i]=(int)pos;
  303.    msg(Window,"No playback rate specified -- 350 used");
  304.    lseek(in,0L,0);    /* rewind */
  305.    }
  306.  
  307. else {
  308.    read(in,&x,4);    /* skip length */
  309.    read(in,&x,4);    /* get form type */
  310.    if (x!=SVX) {
  311.       msg(Window,"File is IFF, but not form 8SVX !!");
  312.       close(in);
  313.       return(-1);
  314.       }
  315.  
  316.    samp->type[i]=RIGHT;   /* default if IFF but not Perfect Sound IFF */
  317.  
  318.    getchunk:
  319.  
  320.    read(in,&x,4);     /* get chunk type */
  321.    while (x!=BODY && x!=CHAN && x!=VHDR) {    /* skip if not what we want */
  322.       skip(in);
  323.       read(in,&x,4);
  324.       if (x==-1 || x==0) {
  325.          msg(Window,"Bad IFF file--Can't load.");
  326.          close(in);
  327.          return(-1);
  328.          }
  329.       }
  330.  
  331.    if (x==CHAN) {
  332.       read(in,&x,4);
  333.       if (x!=4) {
  334.          msg(Window,"Bad CHAN length.");
  335.          close(in);
  336.          return(-1);
  337.          }
  338.       read(in,&samp->type[i],4);
  339.       if (samp->type[i]!=STEREO && samp->type[i]!=RIGHT
  340.           && samp->type[i]!=LEFT) samp->type[i]=RIGHT;
  341.       goto getchunk;
  342.       }
  343.  
  344.    if (x==VHDR) {
  345.       read(in,&x,4);  /* should be 20, length of VHDR */
  346.       if (x!=20) {
  347.          msg(Window,"Format error--invalid length for VHDR");
  348.          close (in);
  349.          return(-1);
  350.          }
  351.       read(in,&samp->oneshot[i],4); /* should be length of sample */
  352.       read(in,&samp->repeat[i],4);
  353.       read(in,&samp->cycles[i],4);
  354.       read(in,&z,2);   /* get samples per second */
  355.       read(in,&samp->ctoctave[i],1);
  356.       if (samp->repeat[i]==0 && samp->ctoctave[i]==1)
  357.       sprintf(line,"File type is IFF -- Playback rate (samples/second) is %d",z);
  358.       else
  359.          sprintf(line,"File is an IFF instrument file with %d octaves.",
  360.                  samp->ctoctave[i]);
  361.       msg(Window,line);
  362.       samp->rate[i]=(int)(1.0/(float)z*3579546.5);
  363.       read(in,&comp,1);
  364.       lseek(in,4L,1);    /* skip volume */
  365.       goto getchunk;
  366.       }
  367.  
  368.  
  369.     /* this must be a body (only thing left) */
  370.  
  371.    read(in,&samp->length[i],4);
  372.    if (samp->type[i]==STEREO) samp->length[i]=samp->length[i]>>1;
  373.    }
  374.  
  375. /* read in data--either BODY or dump */
  376.  
  377. len=samp->length[i];
  378. if (comp==1) len=(len-2)*2;
  379. samp->lmem[i]=AllocMem(len,0);
  380. if (samp->lmem[i]==0) {
  381.    msg(Window,"File to large for available memory.");
  382.    close(in);
  383.    return(-1);
  384.     }
  385. samp->rmem[i]=samp->lmem[i];
  386. if (samp->type[i]==STEREO) {
  387.    samp->rmem[i]=AllocMem(len,0);
  388.    if (samp->rmem[i]==0) {
  389.       msg(Window,"File to large for available memory.");
  390.       FreeMem(samp->lmem[i],len);
  391.       close(in);
  392.       return(-1);
  393.       }
  394.    }
  395.  
  396. if (samp->type[i]==STEREO || samp->type[i]==LEFT) {
  397.    if (comp==0)  
  398.       e1=read(in,samp->lmem[i],samp->length[i]);     /* read in sample */
  399.    if (comp==1)
  400.       e1=cread(in,samp->lmem[i],samp->length[i]);     /* read in sample */
  401.    }
  402.  
  403. if (samp->type[i]==STEREO || samp->type[i]==RIGHT) {
  404.    if (comp==0)
  405.      e2=read(in,samp->rmem[i],samp->length[i]);     /* read in sample */
  406.    if (comp==1)
  407.      e2=cread(in,samp->rmem[i],samp->length[i]);     /* read in sample */
  408.    }
  409.  
  410. close(in);
  411.  
  412. if (e1==-1 || e2==-1) {
  413.    msg(Window,"ERROR loading file!");
  414.    return(-1);
  415.    }
  416.  
  417.  
  418. /* get sample name */
  419.  
  420. samp->length[i]=len;
  421. samp->name[i]=AllocMem(strlen(name)+1,0);
  422. if (samp->name[i]==0) {
  423.    nomem(Window);
  424.    return(-1);
  425.    }
  426. strcpy(samp->name[i],name);        /* put filename in sample structure */
  427.  
  428. PutName(Window,samp->name[*current],*current,REG_VID);
  429. *current=i;
  430. PutName(Window,samp->name[i],i,REV_VID);
  431. if (comp==1) msg(Window,"This File was compressed 'Fibonacci-delta'");
  432. return(0);
  433. }
  434.  
  435. /****************************/
  436. /* compresed data read    ***/
  437. /****************************/
  438. cread(fp,data,len)
  439. int fp;
  440. register int len;
  441. register char *data;
  442. {
  443. BYTE x,d;
  444. register LONG i,j;
  445. BYTE buf[512];
  446.  
  447. read(fp,&d,1);   /* skip padding */
  448. read(fp,&x,1);   /* get inital value */
  449.  
  450. len=len-2;
  451. if (read(fp,buf,min(512,len))==-1) return(-1);
  452. j=0;
  453. for (i=0;i<len;i++) {
  454.    *data=x+delta[15&(buf[j]>>4)];
  455.    x=*data++;
  456.    *data=x+delta[buf[j++]&15];
  457.    x=*data++;
  458.    if (j==512) {
  459.       j=0;
  460.       if (read(fp,buf,min(512,(len-i-1)))==-1) return(-1);
  461.       }
  462.    }
  463. return(0);
  464. }
  465.  
  466.  
  467.  
  468. /**********************/
  469. /**    skip a form    */
  470. /**********************/
  471.  
  472. skip(in)
  473. int in;
  474.  
  475. {
  476. ULONG x;
  477. read(in,&x,4);  /* get lenth */
  478. lseek(in,x,1);  /* seek past it */
  479. if ((x&1)==1)
  480.    lseek(in,1L,1);  /* skip padding if odd */
  481. }
  482.  
  483.  
  484. /**************************/
  485. /**  about perfect sound **/
  486. /**************************/
  487.  
  488. aboutps(Window)
  489.  
  490.  
  491. struct Window *Window;
  492. {
  493. int fp;
  494.  
  495. fp=Open("RAW:56/12/528/188/About Perfect Sound",MODE_NEWFILE);
  496. if (fp==0) {
  497.    msg(Window,"ERROR -- can't open AmigaDOS RAW:");
  498.    return(0);
  499.    }
  500.  
  501. pr(fp,"");
  502. pr(fp,"This program, \"The Perfect Sound Sound Editor,\" is");
  503. pr(fp,"copyrighted 1986 by Anthony J. Wood. You are free");
  504. pr(fp,"to distribute copies of this program for non ");
  505. pr(fp,"commercial use, and if  you enjoy this program,");
  506. pr(fp,"feel free to send lots of money to the address below.");
  507. pr(fp,"Seriously, $20 will buy you a manual, update info, and");
  508. pr(fp,"our appreciation.");
  509. pr(fp,"");
  510. pr(fp,"This sound editor was written to support the");
  511. pr(fp,"\"Perfect Sound\" Audio digitizer. You can");
  512. pr(fp,"purchase The Perfect Sound stereo digitizer, ");
  513. pr(fp,"Sound Editor with source code, Manual, and a");
  514. pr(fp,"Library of recorded sounds (gunshots, splashes,");
  515. pr(fp,"laughing, etc.) for $79.95 from the address below.");
  516. pr(fp,"Order by phone or letter. There is no P&H, however,");
  517. pr(fp,"Texas residents should include 5% sales tax.");
  518. pr(fp,"Dealer inquiries are welcome.");
  519. waitkey(fp);
  520. pr(fp,"\n\n\n\n\n\n");
  521. pr(fp,"                    SunRize Industries");
  522. pr(fp,"                      PO Box 1453");
  523. pr(fp,"                College Station, TX 77841");
  524. pr(fp,"                    (409) 846-1311");
  525. waitkey(fp);
  526. Close(fp);
  527. }
  528.  
  529.  
  530. /****************************/
  531. /** print a line to dos fp  */
  532. /****************************/
  533.  
  534. pr(fp,string)
  535.  
  536. int fp;
  537. char *string;
  538. {
  539. UBYTE newline=10;
  540.  
  541. Write(fp,string,strlen(string));
  542. Write(fp,&newline,1);
  543. }
  544.  
  545. /******************************/
  546. /** wait for a key press     **/
  547. /*****************************/
  548.  
  549. waitkey(fp)
  550. int fp;
  551. {
  552. char xx;
  553. pr(fp,"");
  554. pr(fp,"Press any key to continue...");
  555. Read(fp,&xx,1);
  556. pr(fp,"\014");
  557. }
  558.  
  559. /**********************************/
  560. /**  request a file name         **/
  561. /**********************************/
  562.  
  563. getfile(Window,fname,drawer,ok,title)
  564.  
  565. struct Window *Window;
  566. char *fname,*drawer;
  567. char *ok,*title;
  568.  
  569.  
  570. {
  571. extern WORD diskchange;
  572. static char blank[]="                            ";
  573. char line[80];
  574. int i;
  575. int class,code,x,y;
  576. SHORT ver;
  577. static int top,numfiles,vpot;
  578. struct Gadget *address;
  579. static char undo[80];
  580. static char fn[90][36];
  581. static int ft[80];
  582. static struct Border b[4];
  583. static struct IntuiText t[5];
  584. static struct IntuiText nt[SHOW];
  585. static struct Gadget g[5];
  586. static struct Gadget name[SHOW];
  587. static struct StringInfo s[2];
  588. static struct PropInfo prop;
  589. static struct Requester loadreq;
  590. static struct IntuiMessage *message;
  591. static struct Image image;
  592.  
  593. static SHORT bd0[]={0,0,
  594.                     274,0,
  595.                     274,149,
  596.                     0,149,
  597.                     0,0,
  598.                     0,1,
  599.                     273,1,
  600.                     273,148,
  601.                     1,148,
  602.                     1,0,
  603.                     0,0,
  604.                     0,12,
  605.                     274,12};
  606. static SHORT bd1[]={0,100,275,100};
  607. static SHORT bd2[]={30,130,86,130,86,142,30,142,30,130};
  608. static SHORT bd3[]={180,130,
  609.             236,130,
  610.             236,142,
  611.             180,142,
  612.             180,130};
  613.  
  614. int lock,success;
  615. struct FileInfoBlock *info;
  616.  
  617. if (drawer[0]==0) strcpy(drawer,"df0:");
  618.  
  619. if ((info=(struct FileInfoBlock *)
  620.           AllocMem(sizeof(struct FileInfoBlock),0))==0) {
  621.    return(-1);
  622.    }
  623.  
  624. for (i=0;i<4;i++) {
  625.    b[i].DrawMode=JAM1;
  626.    b[i].LeftEdge=0;
  627.    b[i].TopEdge=0;
  628.    b[i].FrontPen=3;
  629.    b[i].BackPen=0;
  630.    b[i].NextBorder=&b[i+1];
  631. }
  632. b[3].NextBorder=NULL;
  633. b[0].Count=13;
  634. b[0].XY=&bd0[0];
  635. b[1].Count=2;
  636. b[1].XY=&bd1[0];
  637. b[2].Count=5;
  638. b[2].XY=&bd2[0];
  639. b[3].Count=5;
  640. b[3].XY=&bd3[0];
  641.  
  642. /** initilize text structures **/
  643.  
  644. for (i=0;i<5;i++) {
  645.    t[i].DrawMode=JAM1;
  646.    t[i].FrontPen=1;
  647.    t[i].BackPen=0;
  648.    t[i].ITextFont=NULL;
  649.    t[i].NextText=&t[i+1];
  650. }
  651.  
  652. t[4].NextText=NULL;
  653.  
  654. t[0].LeftEdge=8;
  655. t[0].TopEdge=105;
  656. t[0].IText="Drawer:";
  657.  
  658. t[1].LeftEdge=23;
  659. t[1].TopEdge=119;
  660. t[1].IText="File:";
  661.  
  662. t[2].LeftEdge=42;
  663. t[2].TopEdge=133;
  664. t[2].IText=ok;
  665.  
  666. t[3].LeftEdge=184;
  667. t[3].TopEdge=133;
  668. t[3].IText="CANCEL";
  669.  
  670. t[4].LeftEdge=70;
  671. t[4].TopEdge=3;
  672. t[4].IText=title;
  673.  
  674. /* add gadgets */
  675. for (i=0;i<SHOW;i++) {
  676.    name[i].GadgetType=REQGADGET|BOOLGADGET;
  677.    name[i].Flags=GADGHCOMP;
  678.    name[i].NextGadget=&name[i+1];
  679.    name[i].Activation=RELVERIFY;
  680.    name[i].GadgetRender=NULL;
  681.    name[i].SelectRender=NULL;
  682.    name[i].GadgetText=&nt[i];
  683.    name[i].LeftEdge=10;
  684.    name[i].TopEdge=i*10+15;
  685.    name[i].Width=230;
  686.    name[i].Height=11;
  687.  
  688.    nt[i].DrawMode=JAM2;
  689.    nt[i].FrontPen=1;
  690.    nt[i].BackPen=2;
  691.    nt[i].ITextFont=NULL;
  692.    nt[i].NextText=NULL;
  693.    nt[i].TopEdge=1;
  694.    nt[i].LeftEdge=0;
  695.    nt[i].IText="";
  696.    }
  697. name[SHOW-1].NextGadget=&g[0];
  698.  
  699. for (i=0;i<5;i++) {
  700.    g[i].GadgetType=REQGADGET;
  701.    g[i].Flags=GADGHNONE;
  702.    g[i].NextGadget=&g[i+1];
  703.    g[i].Activation=RELVERIFY;
  704.    g[i].GadgetRender=NULL;
  705.    g[i].SelectRender=NULL;
  706.    g[i].GadgetText=NULL;
  707. }
  708.  
  709. g[4].NextGadget=NULL;
  710.  
  711. /* load */
  712. g[0].LeftEdge=30;
  713. g[0].TopEdge=130;
  714. g[0].Width=56;
  715. g[0].Height=12;
  716. g[0].GadgetType|=BOOLGADGET;
  717. g[0].Activation|=ENDGADGET;
  718. /* cancel */
  719. g[1].LeftEdge=180;
  720. g[1].TopEdge=130;
  721. g[1].Width=56;
  722. g[1].Height=12;
  723. g[1].GadgetType|=BOOLGADGET;
  724. g[1].Activation|=ENDGADGET;
  725. /* Drawer */
  726. g[2].LeftEdge=70;
  727. g[2].TopEdge=105;
  728. g[2].Width=180;
  729. g[2].Height=15;
  730. g[2].GadgetType|=STRGADGET;
  731. g[2].SpecialInfo=(APTR)&s[0];
  732. g[2].Flags=GADGHCOMP;
  733. /* file */
  734. g[3].LeftEdge=70;
  735. g[3].TopEdge=119;
  736. g[3].Width=180;
  737. g[3].Height=15;
  738. g[3].GadgetType|=STRGADGET;
  739. g[3].SpecialInfo=(APTR)&s[1];
  740. g[3].Flags=GADGHCOMP;
  741. /* autoknob */
  742. g[4].LeftEdge=250;
  743. g[4].TopEdge=13;
  744. g[4].Width=24;
  745. g[4].Height=87;
  746. g[4].GadgetType|=PROPGADGET;
  747. g[4].SpecialInfo=(APTR)∝
  748. g[4].GadgetRender=ℑ
  749.  
  750. /* prop structure */
  751. prop.Flags=AUTOKNOB|FREEVERT;
  752. prop.HorizPot=0;
  753. prop.VertPot=0;
  754. prop.HorizBody=0xFFFF;
  755. prop.VertBody=0xFFFF;
  756.  
  757.  
  758. /* string gadget info */
  759.  
  760. s[0].Buffer=drawer;
  761. s[1].Buffer=fname;
  762.  
  763. for (i=0;i<2;i++) {
  764.    s[i].UndoBuffer=undo;
  765.    s[i].BufferPos=0;
  766.    s[i].DispPos=0;
  767.    s[i].MaxChars=80;
  768. }
  769.  
  770.  
  771. InitRequester(&loadreq);
  772.  
  773. loadreq.LeftEdge=15;
  774. loadreq.TopEdge=11;
  775. loadreq.Width=275;
  776. loadreq.Height=150;
  777. loadreq.ReqBorder=&b[0];
  778. loadreq.ReqText=&t[0];
  779. loadreq.ReqGadget=&name[0];
  780. loadreq.BackFill=2;   /* black */
  781.  
  782. Request(&loadreq,Window);
  783. if (diskchange==FALSE) goto quick;
  784.  
  785. /**  load current dir **/
  786.  
  787. newdir:
  788. lock=Lock(drawer,ACCESS_READ);
  789. if (lock==0) {
  790.    numfiles=0;
  791.    top=0;
  792.    goto fresh;
  793.    }
  794.  
  795. if ((success=Examine(lock,info))==0) {
  796.    FreeMem(info,sizeof(struct FileInfoBlock));
  797.    return(-1);
  798.    }
  799.  
  800. ExNext(lock,info);  /* skip volume name */
  801.  
  802. i=0;
  803. do {
  804.    strncpy(fn[i],info->fib_FileName,30);
  805.    ft[i]=info->fib_DirEntryType;   /* + is dir, - is file */
  806.    if (ft[i]>0) strcpy(fn[i]+strlen(fn[i])," (dir)");
  807.    i++;
  808.    } while (i<90 && ExNext(lock,info)!=0);
  809. UnLock(lock);
  810. numfiles=i;
  811. diskchange=FALSE;
  812. top=0;  /* 1st file shown in list */
  813. vpot=0;  /* prop position */
  814.  
  815. quick:
  816.  
  817. ver=(WORD)((float)0xFFFF*(float)SHOW/(float)numfiles);
  818. ModifyProp(&g[4],Window,&loadreq,AUTOKNOB|FREEVERT,0,vpot,0xFFFF,ver);
  819. fresh:
  820.  
  821. for (i=0;i<SHOW;i++)
  822.    nt[i].IText=blank;
  823.  
  824. RefreshGadgets(&name[0],Window,&loadreq);
  825.  
  826. for (i=top;i<top+SHOW;i++) {
  827.    if (i<numfiles) nt[i-top].IText=fn[i];
  828.    }
  829.  
  830. RefreshGadgets(&name[0],Window,&loadreq);
  831.  
  832. /* wait for a msg */
  833. loop:
  834. Wait(1<<Window->UserPort->mp_SigBit);
  835.  
  836. while (message=GetMsg(Window->UserPort)) {
  837. class=message->Class;
  838. code=message->Code;
  839. address=message->IAddress;
  840. x=message->MouseX;
  841. y=message->MouseY;
  842. ReplyMsg(message);
  843.  
  844. if (class!=GADGETUP) {
  845.    goto skip;
  846.    }
  847.  
  848. if (address==&g[0]) {    /* Load file */
  849.    FreeMem(info,sizeof(struct FileInfoBlock));
  850.    return(0);
  851.    }
  852.  
  853. if (address==&g[1]) {   /* cancel */
  854.    FreeMem(info,sizeof(struct FileInfoBlock));
  855.    return(-1);
  856.    }
  857.  
  858. if (address==&g[2]) {    /* drawer */
  859.    goto newdir;
  860.    }
  861.  
  862. if (address==&g[4]) {  /* prop gadget */
  863.    top=prop.VertPot*numfiles/0xFFFF;
  864.    vpot=prop.VertPot;
  865.    goto fresh;
  866.    }
  867.  
  868. for (i=0;i<SHOW;i++)  /* picking an entry? */
  869.    if (&name[i]==address) {
  870.       i=i+top;
  871.       if (i>=numfiles) goto skip;
  872.       if (ft[i]>0) {      /* directory */
  873.          strncpy(line,fn[i],strlen(fn[i])-6);
  874.          add(drawer,line);
  875.          goto newdir;
  876.          }
  877.       else {
  878.          strcpy(fname,fn[i]);
  879.          RefreshGadgets(&name[0],Window,&loadreq);
  880.          }
  881.       }
  882.  
  883. skip: ;
  884. }
  885. goto loop;
  886. }
  887.  
  888.  
  889. /************************/
  890. /** extend filename     */
  891. /************************/
  892.  
  893. add(to,from)
  894. char *to,*from;
  895. {
  896.  
  897. int i;
  898.  
  899. if (*to==0) {
  900.    strcpy(to,from);
  901.    return(0);
  902.    }
  903. if (to[strlen(to)-1]==':') {
  904.    strcpy(to+strlen(to),from);
  905.    return(0);
  906.    }
  907. to[(i=strlen(to))]='/';
  908. strcpy(to+i+1,from);
  909. }
  910.  
  911. /*****************************/
  912. /** request an integer value */
  913. /*****************************/
  914.  
  915. getint(Window,ival,imin,imax,title,width)
  916.  
  917. struct Window *Window;
  918. int ival,width,imin,imax;
  919. char *title;
  920.  
  921. {
  922. struct Border b;
  923. struct IntuiText t[2];
  924. struct Gadget g[3];
  925. struct StringInfo s;
  926. struct PropInfo prop;
  927. struct Requester loadreq;
  928. struct IntuiMessage *message;
  929. struct Image image;
  930. int class,code,x,y;
  931. struct Gadget *address;
  932. char undo[80],ascii[80];
  933. int i,hor;
  934. static SHORT bd[]={0,0,          /* 99 are changed below */
  935.                    99,0,
  936.                    99,IHI-1,
  937.                    0,IHI-1,
  938.                    0,0,
  939.                    0,11,
  940.                    99,11};
  941.  
  942. bd[2]=width-1;
  943. bd[4]=bd[2];
  944. bd[12]=bd[2];
  945.  
  946. /* initilize string (int) gadget */
  947. stci_d(ascii,ival,80);
  948.  
  949.  
  950.    b.DrawMode=JAM1;
  951.    b.LeftEdge=0;
  952.    b.TopEdge=0;
  953.    b.FrontPen=3;
  954.    b.BackPen=0;
  955.    b.NextBorder=NULL;
  956.    b.NextBorder=NULL;
  957.    b.Count=7;
  958.    b.XY=&bd[0];
  959.  
  960. /** initilize text structures **/
  961.  
  962. for (i=0;i<2;i++) {
  963.    t[i].DrawMode=JAM1;
  964.    t[i].FrontPen=1;
  965.    t[i].BackPen=0;
  966.    t[i].ITextFont=NULL;
  967.    t[i].NextText=&t[i+1];
  968. }
  969.  
  970. t[1].NextText=NULL;
  971.  
  972. t[0].LeftEdge=(width-8*strlen(title))/2;
  973. t[0].TopEdge=2;
  974. t[0].IText=title;
  975.  
  976. t[1].LeftEdge=width-60;
  977. t[1].TopEdge=IHI-15;
  978. t[1].IText=" OK! ";
  979. t[1].DrawMode=JAM2;
  980.  
  981. /* add gadgets */
  982.  
  983. for (i=0;i<3;i++) {
  984.    g[i].GadgetType=REQGADGET;
  985.    g[i].Flags=GADGHCOMP;
  986.    g[i].NextGadget=&g[i+1];
  987.    g[i].Activation=RELVERIFY;
  988.    g[i].GadgetRender=NULL;
  989.    g[i].SelectRender=NULL;
  990.    g[i].GadgetText=NULL;
  991. }
  992.  
  993. g[2].NextGadget=NULL;
  994.  
  995. /* ok! */
  996. g[0].LeftEdge=width-60;
  997. g[0].TopEdge=IHI-15;
  998. g[0].Width=40;
  999. g[0].Height=8;
  1000. g[0].GadgetType|=BOOLGADGET;
  1001. g[0].Activation|=ENDGADGET;
  1002.  
  1003. /* int string (enter value) */
  1004. g[2].LeftEdge=30;
  1005. g[2].TopEdge=IHI-15;
  1006. g[2].Width=42;
  1007. g[2].Height=11;
  1008. g[2].GadgetType|=STRGADGET;
  1009. g[2].Activation|=LONGINT|STRINGCENTER;
  1010. g[2].SpecialInfo=(APTR)&s;
  1011.  
  1012. /* autoknob */
  1013. g[1].LeftEdge=10;
  1014. g[1].TopEdge=20;
  1015. g[1].Width=width-20;
  1016. g[1].Height=9;
  1017. g[1].GadgetType|=PROPGADGET;
  1018. g[1].SpecialInfo=(APTR)∝
  1019. g[1].GadgetRender=ℑ
  1020. g[1].Activation=FOLLOWMOUSE|GADGIMMEDIATE;
  1021. g[1].Flags=GADGHNONE;
  1022.  
  1023. /* prop structure */
  1024. prop.Flags=AUTOKNOB|FREEHORIZ;
  1025. prop.HorizPot=(SHORT)((LONG)(ival-imin)*(LONG)0xFFFF/(LONG)(imax-imin));
  1026. prop.VertPot=0;
  1027. prop.HorizBody=1;
  1028. prop.VertBody=0xFFFF;
  1029.  
  1030.  
  1031. /* string gadget info */
  1032.  
  1033. s.Buffer=ascii;
  1034. s.UndoBuffer=undo;
  1035. s.BufferPos=0;
  1036. s.DispPos=0;
  1037. s.MaxChars=80;
  1038. s.LongInt=ival;
  1039.  
  1040.  
  1041. InitRequester(&loadreq);
  1042.  
  1043. loadreq.LeftEdge=100;
  1044. loadreq.TopEdge=50;
  1045. loadreq.Width=width;
  1046. loadreq.Height=IHI;
  1047. loadreq.ReqBorder=&b;
  1048. loadreq.ReqText=&t[0];
  1049. loadreq.ReqGadget=&g[0];
  1050. loadreq.BackFill=2;   /* black */
  1051.  
  1052. Request(&loadreq,Window);
  1053.  
  1054. loop:
  1055. Wait(1<<Window->UserPort->mp_SigBit);
  1056.  
  1057. while (message=GetMsg(Window->UserPort)) {
  1058.    class=message->Class;
  1059.    code=message->Code;
  1060.    address=(struct Gadget *)message->IAddress;
  1061.    x=message->MouseX;
  1062.    y=message->MouseY;
  1063.    ReplyMsg(message);
  1064. }
  1065.  
  1066. if (class==GADGETUP && address==&g[0]) {  /* ok! */
  1067.    return((int)s.LongInt);
  1068.    }
  1069.  
  1070. if (class==MOUSEMOVE) {
  1071.    ival=prop.HorizPot*(imax-imin)/0xFFFF+imin;
  1072.    stci_d(ascii,ival,80);
  1073.    s.LongInt=ival;
  1074.    RefreshGadgets(&g[2],Window,&loadreq);
  1075.    }
  1076.  
  1077. if (class==GADGETUP && address==&g[2]) {    /* new integer */
  1078.    ival=s.LongInt;
  1079.    if (ival>imax) ival=imax;
  1080.    if (ival<imin) ival=imin;
  1081.    hor=(int)((LONG)(ival-imin)*(LONG)0xFFFF/(LONG)(imax-imin));
  1082.    ModifyProp(&g[1],Window,&loadreq,AUTOKNOB|FREEHORIZ,hor,0,1,0xFFFF);
  1083.    }
  1084.  
  1085. goto loop;   
  1086.    
  1087. }
  1088. getstr(Window,string,title,width)
  1089.  
  1090. struct Window *Window;
  1091. int width;
  1092. char *title,*string;
  1093.  
  1094. {
  1095. struct Border b;
  1096. struct IntuiText t;
  1097. struct Gadget g;
  1098. struct StringInfo s;
  1099. struct Requester loadreq;
  1100. struct IntuiMessage *message;
  1101. char undo[80];
  1102. static SHORT bd[]={0,0,          /* 99 are changed below */
  1103.                    99,0,
  1104.                    99,SHI-1,
  1105.                    0,SHI-1,
  1106.                    0,0,
  1107.                    0,11,
  1108.                    99,11};
  1109.  
  1110. bd[2]=width-1;
  1111. bd[4]=bd[2];
  1112. bd[12]=bd[2];
  1113.  
  1114.  
  1115. b.DrawMode=JAM1;
  1116. b.LeftEdge=0;
  1117. b.TopEdge=0;
  1118. b.FrontPen=3;
  1119. b.BackPen=0;
  1120. b.NextBorder=NULL;
  1121. b.NextBorder=NULL;
  1122. b.Count=7;
  1123. b.XY=&bd[0];
  1124.  
  1125. /** initilize text structures **/
  1126.  
  1127. t.DrawMode=JAM1;
  1128. t.FrontPen=1;
  1129. t.BackPen=0;
  1130. t.ITextFont=NULL;
  1131. t.NextText=NULL;
  1132. t.LeftEdge=(width-8*strlen(title))/2;
  1133. t.TopEdge=2;
  1134. t.IText=title;
  1135.  
  1136.  
  1137. /* add gadgets */
  1138.  
  1139. g.GadgetType=REQGADGET|STRGADGET;
  1140. g.Flags=GADGHCOMP;
  1141. g.Activation=ENDGADGET|RELVERIFY;
  1142. g.GadgetRender=NULL;
  1143. g.SelectRender=NULL;
  1144. g.GadgetText=NULL;
  1145. g.NextGadget=NULL;
  1146. g.LeftEdge=20;
  1147. g.TopEdge=SHI-15;
  1148. g.Width=width-40;
  1149. g.Height=11;
  1150. g.SpecialInfo=(APTR)&s;
  1151.  
  1152. s.Buffer=string;
  1153. s.UndoBuffer=undo;
  1154. s.BufferPos=0;
  1155. s.DispPos=0;
  1156. s.MaxChars=80;
  1157.  
  1158. InitRequester(&loadreq);
  1159.  
  1160. loadreq.LeftEdge=(640-width)/2;
  1161. loadreq.TopEdge=50;
  1162. loadreq.Width=width;
  1163. loadreq.Height=SHI;
  1164. loadreq.ReqBorder=&b;
  1165. loadreq.ReqText=&t;
  1166. loadreq.ReqGadget=&g;
  1167. loadreq.BackFill=2;   /* black */
  1168.  
  1169. Request(&loadreq,Window);
  1170.  
  1171. again:
  1172. Wait(1<<Window->UserPort->mp_SigBit);
  1173. while(message=GetMsg(Window->UserPort)) {
  1174.    if (message->Class==GADGETUP) {
  1175.       ReplyMsg(message);
  1176.       return(0);
  1177.       }
  1178.    ReplyMsg(message);
  1179.    }
  1180. goto again;
  1181.  
  1182. }
  1183.